package com.gpj.netty.application.netty.base;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

/**
 * @className NettyServer
 * @description Netty服务端基本代码
 * @author GPJ
 * @date 2021-12-06 17:03
 * @version 1.0
 **/
@Slf4j
public class NettyServer {
	public static void main(String[] args) throws InterruptedException {
		// 创建线程组bossGroup,用于处理链接请求 (NioEventLoop的子线程个数默认为cpu核数的两倍)
		EventLoopGroup bossGroup = new NioEventLoopGroup(1);
		// 创建线程组workGroup,用于和客户端业务处理 (NioEventLoop的子线程个数默认为cpu核数的两倍)
		EventLoopGroup workGroup = new NioEventLoopGroup(1);

		// 创建服务器端的启动对象
		ServerBootstrap bootstrap = new ServerBootstrap();

		// 设置线程组
		bootstrap.group(bossGroup, workGroup);

		// 服务器的通道实现
		bootstrap.channel(NioServerSocketChannel.class);

		/**
		 * 初始化服务器连接队列大小
		 *  * 服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接
		 *  * 多个客户端同时来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理
		 */
		bootstrap.option(ChannelOption.SO_BACKLOG, 1024);

		// 创建通道初始化对象,设置初始化参数,在 SocketChannel 建立起来之前执行
		bootstrap.childHandler(new ChannelInitializer<SocketChannel>(){
			@Override
			protected void initChannel(SocketChannel socketChannel) {
				// 对workerGroup的SocketChannel设置处理器
				socketChannel.pipeline().addLast(new ServerHandler());
			}
		});

		log.debug("netty server starting...");

		/**
		 * 绑定端口并启动服务
		 *  * ChannelFuture -- 异步对象
		 *  * 通过isDone()等方法可以判断异步事件的执行情况
		 *  * 通过sync()方法可进行阻塞等待服务启动完成
		 *  * 可通过addListener()方法可注册监听事件,用于监听服务启动等事件
		 */
		ChannelFuture cf = bootstrap.bind(9000);
		cf.addListener(new ChannelFutureListener() {
			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				if (cf.isSuccess()) {
					log.debug("监听端口9000成功");
				} else {
					log.debug("监听端口9000失败");
				}
			}
		});
		cf.sync();

		// 等待服务端监听端口关闭
		cf.channel().closeFuture().sync();
	}
}
